home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-24 | 24.4 KB | 652 lines | [TEXT/pdos] |
- *******************************************************************************
- *
- * BoxCtl CDEFProc -- Version 3.0
- *
- * (C) Copyright Apple Computer, Inc. 1988-1990
- * All rights reserved.
- *
- * Developer Technical Support Apple II Sample Code
- *
- * by Keith Rollin
- *
- * This is a Custom Control for the Apple IIGS. It is similar in appearance
- * and action to the 'resize' box you get when clicking on an object in GS Draw
- * or MacDraw.
- *
- * The Control is essentially a frame with 4 or 8 grow knobs on the corners
- * and/or edges. Dragging on any of these knobs will grow the control. Dragging
- * on the frame will move the entire control (like moving a window). A flag can
- * be set so that the control will be dragged if the user clicks in the interior
- * of the control as well. Part codes for the knobs and frame are listed below.
- *
- * Snapping the rectangle's coordinates to a grid is also supported. The
- * rectangle is snapped to the nearest point on the grid. This effectively means
- * that I perform rounding, and not truncating.
- *
- * The frame of the control is the rectangle passed to NewControl. The size of
- * the knobs and the size of the grid are passed in ctlValue. The 'interior drag
- * flag' is passed in ctlFlags. See below for details.
- *
- * Color is supported. Currently, only two colors are used: one for the frame,
- * and one for the knobs. The default colors are black.
- *
- *******************************************************************************
- *
- * Part Code returned:
- *
- * $A0 for all parts of the control (all parts are 'indicators')
- *
- *
- * CtlValue: Bits 8-15: width of grow knobs
- * Bits 0- 7: height of grow knobs
- *
- * CtlFlag bits:
- * 7 = 1 - Control is invisible
- * = 0 - Control is visible
- * 2 = 1 - Has edge knobs
- * = 0 - Doesn't
- * 1 = 1 - Has corner knobs
- * = 0 - Doesn't
- * 0 = 1 - Clicking in interior will drag control
- * = 0 - Clicking in interior does nothing
- *
- * Data: Contains a pointer to the following data block. This data
- * block holds the following information, which is copied to
- * the end of the control record:
- *
- * WORD: Min Y when growing
- * WORD: Min X when growing
- * WORD: Max Y when growing
- * WORD: Max X when growing
- * WORD: Spacing for Y segment of grid
- * WORD: Spacing for X segment of grid
- *
- * Color Table:
- * WORD: Bits 12-15: <reserved>
- * 8-11: Knob Color
- * 4- 7: Inactive Frame/Knob Color
- * 0- 3: Frame Color
- *
- *******************************************************************************
- *
- * How to use the Control:
- *
- * Initialization and tracking of the control work just like any other;
- * set it up with NewControl. When GetNextEvent returns inContent, call
- * FindControl to see if you hit the control. If you did, call
- * TrackControl.
- *
- * Initialization:
- *
- * pha ; space for result
- * pha
- * PushLong theWindow
- * PushLong #theRect ; pointer to bounding rectangle
- * PushLong #0 ; no title
- * PushWord #%00000111 ; vis, int will drag, corners & edges
- * PushWord #$0503 ; Width = 5/Height = 3
- * PushLong #CtrlData ; Pointer to additional data
- * PushLong #BoxProc ; pointer to DefProc
- * PushLong #0 ; refcon
- * PushLong #0 ; use std color table
- * _NewControl
- * PullLong theControl
- *
- * theRect dc i2'' 50,140,110,300
- * CtrlData dc i2'' 10 ; min Y
- * dc i2'' 10 ; min X
- * dc i2'' 100 ; max Y
- * dc i2'' 200 ; max X
- * dc i2'' 16 ; grid Y
- * dc i2'' 32 ; grid X
- *
- *******************************************************************************
- **********************************************************************
- * *
- * Apple IIGS Source Code Sampler, Volume I *
- * *
- * Copyright (c) Apple Computer, Inc. 1988 *
- * All Rights Reserved *
- * *
- * Written by Apple II Developer Tech Support *
- * *
- * *
- * *
- * ---------------------------------------------------------------- *
- * *
- * This program and its derivatives are licensed only for *
- * use on Apple computers. *
- * *
- * Works based on this program must contain and *
- * conspicuously display this notice. *
- * *
- * This software is provided for your evaluation and to *
- * assist you in developing software for the Apple IIGS *
- * computer. *
- * *
- * DISCLAIMER OF WARRANTY *
- * *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT *
- * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, *
- * WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS *
- * FOR ANY PARTICULAR PURPOSE. THE ENTIRE RISK AS TO *
- * THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH *
- * YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND *
- * NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE) *
- * ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, *
- * REPAIR OR CORRECTION. *
- * *
- * Apple does not warrant that the functions *
- * contained in the Software will meet your requirements *
- * or that the operation of the Software will be *
- * uninterrupted or error free or that defects in the *
- * Software will be corrected. *
- * *
- * SOME STATES DO NOT ALLOW THE EXCLUSION *
- * OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY *
- * NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC *
- * LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS *
- * WHICH VARY FROM STATE TO STATE. *
- * *
- * *
- **********************************************************************
- eject
- ;-------------------------------------------
- ;
- ; --- Constants
- ;
- ; --- Stack Frame/Local Direct Page usage
- ;
-
- OrigD gequ 1 ; caller's saved direct page register
- OrigB gequ OrigD+2 ; caller's saved data bank register
- work gequ OrigB+1 ; general use work space
- CtlPtr gequ work+4 ; pointer to control record
- RtnAddr gequ CtlPtr+4 ; RTL address back to Control Manager
- theCtlHandle gequ RtnAddr+3 ; handle to control record
- CtlParam gequ theCtlHandle+4 ; add'l parameter passed to DefProc
- CtlCode gequ CtlParam+4 ; operation to perform
- ReturnValue gequ CtlCode+2 ; space for return value to Ctl Mgr.
-
- ;
- ; --- Offsets for my control record
- ;
-
- oCtlMinY gequ octlColor+4
- oCtlMinX gequ oCtlMinY+2
- oCtlMaxY gequ oCtlMinX+2
- oCtlMaxX gequ oCtlMaxY+2
- oCtlGridY gequ oCtlMaxX+2
- oCtlGridX gequ oCtlGridY+2
- oCtlSize gequ oCtlGridX+2
-
- ;
- ; --- Part codes for my control
- ;
-
- BoxCtlPart gequ $A0 ; This is returned to the app.
-
- FramePart gequ $01 ; These are used internally to tell
- InteriorPart gequ $02 ; 'myDragCtl' what part of the
- ULPart gequ $03 ; control we are dragging.
- TopPart gequ $04
- URPart gequ $05
- RightPart gequ $06
- LLPart gequ $07
- BottomPart gequ $08
- LRPart gequ $09
- LeftPart gequ $0A
-
-
- ;
- ; --- Masks for ctlFlags
- ;
-
- dragIntMask gequ %00000001 ; if set, let user drag on interior
- knobCornerMask gequ %00000010 ; if set, draw knobs on the corners
- knobEdgeMask gequ %00000100 ; if set, draw knobs on the edges
- visMask gequ ctlInVis
-
- EJECT
- *******************************************************************************
- *
- CtlData data
- *
- * Description: Storage for CDEF
- *
- *
- * External Refs: NONE
- *
- * Entry Points: NONE
- *
- *******************************************************************************
-
- deltaX ds 2 ; used when growing the control
- deltaY ds 2
- ColorPtr ds 4 ; pointer to actual color table to use
- theParam ds 4 ; copy of CtlParam passed on stack
- dragPart ds 2 ; internal part of control hit
-
- myCtlRect ds 8 ; copy of CtlRect in control record
- myCtlGridY ds 2 ; copy of CtlGridY
- myCtlGridX ds 2 ; copy of CtlGridX
-
- FrameHeight ds 2
- FrameWidth ds 2
-
- knobUL ds 8 ; This space is used to store the
- knobTop ds 8 ; rectangles that define the grow
- knobUR ds 8 ; knobs on the control. They are
- knobRight ds 8 ; created as needed, and are not
- knobLR ds 8 ; stored in the control record.
- knobBottom ds 8
- knobLL ds 8
- knobLeft ds 8
-
- StdColorTable dc i1'$C0' ; grey inact frame, blk normal frame
- dc i1'$00' ; black knobs
- StdCtlData dc i2'10,10,200,640,0,0' ; min 10,10; max 200,640; no grid
- oldPenState ds $32 ; storage for old pen state.
-
- GreyPattern dc i1'$CC,$CC,$CC,$CC,$CC,$CC,$CC,$CC'
- dc i1'$CC,$CC,$CC,$CC,$CC,$CC,$CC,$CC'
- dc i1'$CC,$CC,$CC,$CC,$CC,$CC,$CC,$CC'
- dc i1'$CC,$CC,$CC,$CC,$CC,$CC,$CC,$CC'
-
- end
-
- EJECT
- *******************************************************************************
- *
- BoxProc start
- *
- * Description: Main Routine for Custom Control.
- *
- *
- * Inputs: On entry, the parameters are passed to us on the stack.
- *
- * | | Previous Contents
- * |-------------------|
- * | ReturnValue | LONG - Space for return value
- * |-------------------|
- * | CtlCode | WORD - operation to perform
- * |-------------------|
- * | CtlParam | LONG - add'l parameter
- * |-------------------|
- * | theCtlHandle | LONG - Handle to control record
- * |-------------------|
- * | RtnAddr | 3 BYTES - RTL address
- * |-------------------|
- * | | <-- Stack pointer
- *
- * Outputs: Put something into ReturnValue, pull off the parameters,
- * and return to the Control Manager.
- *
- * | | Previous Contents
- * |-------------------|
- * | ReturnValue | LONG - Space for return value
- * |-------------------|
- * | RtnAddr | 3 BYTES - RTL address
- * |-------------------|
- * | | <-- Stack pointer
- *
- * External Refs:
- * Import InitCtlData
- * Import myDrawCtl
- * Import myTestCtl
- * Import myInitCtl
- * Import myDragCtl
- * Import myNewValue
- * Import mySetParams
- * Import myRecSize
- * Import Null
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using CtlData
-
- ;
- ; We are going to be using the stack as our direct page for the
- ; custom control. The equates listed at the beginning of the custom
- ; control (right after the pageful of comments that explain it)
- ; describe the layout of the stack frame.
- ;
- ; The way we set up the stack frame as our direct page is by first
- ; saving the old contents of the DP register, transfering the stack
- ; pointer to the accumulator, and then transferring that to the DP
- ; register. We also save the contents of the Data Bank Register and
- ; reset it to the Program Bank Register so that we don't have to
- ; use 3-byte long addressing anywhere. We will restore both of these
- ; registers when we leave the custom control.
- ;
-
- pha ; push on some room for 'CtlPtr'
- pha
- pha ; push on some room for 'work'
- pha
-
- phb ; save the Data Bank register
- phd ; save the Direct Page register
-
- phk ; switch data bank to program bank
- plb
- tsc ; switch Direct Page into stack
- tcd
-
- jsr InitCtlData ; init some handy data
-
- lda <CtlCode ; get routine # to call
- cmp #recSize+1 ; we only know of 12 CtlCodes
- blt ShiftIt
- lda #6 ; force unknown codes to null events
- ShiftIt ANOP
- asl a
- tax
- jsr (CtlTable,x)
-
- sta <ReturnValue ; save the return value
- stx <ReturnValue+2
-
- ;
- ; The Return Value has been stored on the stack, and it is time for us to
- ; return back to the Control Manager. Before we do so, however, we must
- ; remove the parameters that were passed to us on the stack. We do this
- ; by moving the RTL address up just below the Return Value, getting the
- ; stack pointer, and adding an amount to it so that we point to where
- ; the RTL address has been moved to. We can then simply RTL back to the
- ; Control Manager, and it will pick up the Return Value right off of the
- ; stack!
- ;
- lda <RtnAddr ; move the return address up
- sta <ReturnValue-3
- lda <RtnAddr+1
- sta <ReturnValue-2
-
- tsc ; Get the stack pointer
-
- pld ; restore caller's Data Bank and
- plb ; Direct Page registers
-
- clc ; Adjust the stack pointer to point to
- adc #ReturnValue-4 ; the new location of the RTL address.
- tcs ; Put the stack pointer back.
-
- rtl ; back to the caller
-
-
- ; This is a table of pointers to routines to be called for specific
- ; CtlCodes passed to us. The 'null' entries are pointers to a
- ; routine that does nothing except return 'no error'.
-
- CtlTable ANOP
- dc i2'myDrawCtl' ; 0 drawCtl
- dc i2'Null' ; 1 calcCRect
- dc i2'myTestCtl' ; 2 testCtl
- dc i2'myInitCtl' ; 3 initCtl
- dc i2'Null' ; 4 dispCtl
- dc i2'Null' ; 5 posCtl
- dc i2'Null' ; 6 thumbCtl
- dc i2'myDragCtl' ; 7 dragCtl
- dc i2'Null' ; 8 autoTrack
- dc i2'myNewValue' ; 9 newValue
- dc i2'mySetParams' ;10 setParams
- dc i2'myInitCtl' ;11 moveCtl
- dc i2'myRecSize' ;12 recSize
-
- end
-
- EJECT
- *******************************************************************************
- *
- myDrawCtl start
- *
- * Description: Draw control command.
- *
- *
- * Inputs: NONE
- *
- * Outputs: NONE
- *
- * External Refs:
- * Import CalcCorners
- * Import SetMyPen
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using CtlData
-
- ; figure out the coordinates of the grow knobs.
-
- jsr CalcCorners
-
- ; Save the pen state, as we'll be changing it a lot.
-
- PushLong #oldPenState
- _GetPenState
-
- ; Set the correct width of the pen for the mode we are in.
-
- jsr SetMyPen
-
- ;
- ; Set the local variable 'ActivFlag' to indicate how to draw the
- ; control. We draw it inactive if a) the Hilite value is 255, or b)
- ; the owner window is inactive and fCtrlTie is set.
- ;
- ldy #octlHilite ; are we inactive?
- lda [<CtlPtr],y
- and #$00FF
- cmp #$00FF
- beq DrawInactive ; yes, so clear ActivFlag
-
- ; At this point, the control can potentially be drawn as an active
- ; control. But this can only happen if the window is active, or is
- ; inactive but with the fCtlTie flag clear.
-
- ldy #octlOwner ; get the pointer to the control's
- lda [<CtlPtr],y ; owning window into 'work'
- sta <work
- iny
- iny
- lda [<CtlPtr],y
- sta <work+2
-
- ldy #owFrame-4 ; get the frame bits
- lda [<work],y
- and #fHilited ; check the Hilite bit
- bne DrawActive ; window is active -> control active
- lda [<work],y ; window is inactive
- and #fCtlTie ; does CtlTie bit affect control?
- bne DrawInactive ; yes, so draw it inactive too
-
- DrawActive lda #1
- sta ActivFlag
- bra SetColorTable
-
- DrawInactive stz ActivFlag
-
- ; Put the color table pointer into a Direct page location.
-
- SetColorTable ANOP
- lda ColorPtr
- sta <work
- lda ColorPtr+2
- sta <work+2
-
- ;
- ; See if the control is active or not, and set the color
- ; accordingly.
- ;
-
- lda ActivFlag
- bne SetFrameColor
-
- lda [<work] ; YES - so we are. Use the inactive
- lsr a ; pattern for this.
- lsr a
- lsr a
- lsr a
- and #$000f
- pha
- _SetSolidPenPat
-
- bra DrawFrame
-
- SetFrameColor ANOP
- lda [<work] ; get the color for the frame from
- and #$000f ; the color table and use it.
- pha
- _SetSolidPenPat
-
- DrawFrame ANOP
- PushLong #myCtlRect ; draw the frame of the control
- _FrameRect
-
- ;
- ; See if the control is active or not, and set the color accordingly. If
- ; we so chose we could even decide not to draw knobs on an inactive sizer.
- ; This is similar to the scrollbar defproc no drawing the thumb on an
- ; inactive scrollbar.
- ;
-
- lda ActivFlag
- beq DrawKnobs ; it's inactive; keep that pattern
-
- lda [<work] ; get the color of the knobs from
- xba ; the color table and set it.
- and #$000f
- pha
- _SetSolidPenPat
-
- DrawKnobs ANOP
- ldy #octlFlag ; do we need corner knobs?
- lda [<CtlPtr],y
- and #knobCornerMask
- beq ckEdges ; no, so check for edge knobs.
-
- PushLong #knobUL ; yes, so draw them
- _PaintRect
-
- PushLong #knobUR
- _PaintRect
-
- PushLong #knobLL
- _PaintRect
-
- PushLong #knobLR
- _PaintRect
-
- ckEdges ANOP
- ldy #octlFlag ; do we need edge knobs?
- lda [<CtlPtr],y
- and #knobEdgeMask
- beq done ; no, so leave
-
- PushLong #knobTop ; yes, so draw them.
- _PaintRect
-
- PushLong #knobRight
- _PaintRect
-
- PushLong #knobBottom
- _PaintRect
-
- PushLong #knobLeft
- _PaintRect
-
- done ANOP
- PushLong #oldPenState ; clean up after ourselves.
- _SetPenState
-
- lda #0
- tax
-
- rts
-
- ActivFlag ds 2
-
- end
-
- EJECT
- *******************************************************************************
- *
- myTestCtl start
- *
- * Description: Hit test command. This routine checks to see if we have
- * chosen the ability to drag the control when we click in
- * the interior or not. If so, then we will always return
- * our partcode (BoxCtlPart = $A0). If not, then we only
- * return our partcode if we click on the frame or a knob.
- *
- *
- * Inputs: NONE
- *
- * Outputs: A = Part code hit
- *
- * External Refs:
- * Import TestFrame
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using CtlData
-
- jsr TestFrame
- cmp #noPart ; hit anything?
- beq exit ; no - return nothing
- lda #BoxCtlPart ; yes - return our partcode
- exit ANOP
- ldx #0 ; high byte of return value always $00
- rts
-
- end
-
- EJECT
- *******************************************************************************
- *
- myInitCtl start
- *
- * Description: Called to initialize my custom fields of the control
- * data. It calles mySetParams to handle the data that
- * is pointed to by the Data/Params field, and makes sure
- * that the corners of the rectangle lie on the grid.
- *
- *
- * Inputs: NONE
- *
- * Outputs: NONE
- *
- * External Refs:
- * Import mySetParams
- * Import Snap2Grid
- * Import SetCtlRect
- * Import InitCtlData
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using CtlData
-
- ; First, set up some fields based on the value of Param. This is
- ; a pointer to some additional data, so what SetParams does is
- ; copy that into our control record.
-
- jsr mySetParams
- jsr InitCtlData
-
- ; Next, make sure the edges of the control are aligned to a grid.
-
- ldx #^myCtlRect
- lda #myCtlRect
- jsr Snap2Grid
-
- jsr SetCtlRect
-
- lda #0 ; return nothing
- txa
-
- rts
- end
-